#include "qelib.h"
#include "ff.h"
#include "diskio.h"



#define FFT_LOGNAME         "fatfs-test"
#define fft_debug(...)      qelog_debug(FFT_LOGNAME,   __VA_ARGS__)
#define fft_info(...)       qelog_info(FFT_LOGNAME,    __VA_ARGS__)
#define fft_notice(...)     qelog_notice(FFT_LOGNAME,  __VA_ARGS__)
#define fft_warning(...)    qelog_warning(FFT_LOGNAME, __VA_ARGS__)
#define fft_error(...)      qelog_error(FFT_LOGNAME,   __VA_ARGS__)
#define fft_hexdump(...)    qehex_debug(FFT_LOGNAME, __VA_ARGS__)



static char ram_disk_space[1024*100] = {0};

static ffdio_dev ram_disk_dev = {
    .pdrv_num = 0,
};

static qe_ret ram_disk_init(ffdio_dev *dev)
{
    fft_debug("init");
    return qe_ok;
}

static qe_ret ram_disk_status(ffdio_dev *dev)
{
    fft_debug("status");
    return qe_ok;
}

static qe_int ram_disk_read(ffdio_dev *, qe_u8* buff, qe_u64 sector, qe_uint count)
{
    char *pos;
    qe_uint size;
    fft_debug("read %d %d", sector, count);
    pos = ram_disk_space + sector * 512;
    size = count * 512;
    qe_memcpy(buff, pos, count * size);
    return 0;
}

static qe_int ram_disk_write(ffdio_dev *, const qe_u8* buff, qe_u64 sector, qe_uint count)
{
    char *pos;
    qe_uint size;
    fft_debug("write %d %d", sector, count);
    pos = ram_disk_space + sector * 512;
    size = count * 512;
    qe_memcpy(pos, buff, count * size);
    return 0;
}

static qe_ret ram_disk_ioctl(ffdio_dev *, qe_u8 cmd, void *buff)
{
    fft_debug("ioctl cmd:%d", cmd);

    switch (cmd) {

    case CTRL_SYNC:
        break;

    case GET_SECTOR_COUNT:
        *(DWORD *)buff = sizeof(ram_disk_space) / 512;
        break;

    case GET_SECTOR_SIZE:
        *(DWORD *)buff = 512;
        break;

    case GET_BLOCK_SIZE:
        *(DWORD *)buff = 1;
        break;

    case CTRL_TRIM:
        break;
    }

    return qe_ok;
}

static ffdio_dev_ops ram_disk_ops = {
    .init   = ram_disk_init,
    .status = ram_disk_status,
    .read   = ram_disk_read,
    .write  = ram_disk_write,
    .ioctl  = ram_disk_ioctl,
};

static MKFS_PARM fs_params = {
    .fmt = FM_ANY,
    .n_fat = 1,
    .align = 0,
    .n_root = 0,
    .au_size = 0
};

FATFS fs;

static char work_buffer[512*8];

int main(int argc, char *argv[])
{
    FIL fp;
    qe_ret ret;
    qe_uint rlen;
    FRESULT res;
    char string[] = "Hello world\r\n";
    char rxbuf[128] = {0};

    qelog_init(QELOG_DEBUG, QELOG_CL|QELOG_DM|QELOG_DATE|QELOG_LV);

    ram_disk_dev.ops = &ram_disk_ops;
    ret = ffdio_dev_register(&ram_disk_dev);
    if (ret != qe_ok) {
        fft_error("ffdio dev register error:%d", ret);
        return -1;
    }

	res = f_mkfs("", &fs_params, work_buffer, sizeof(work_buffer));
	if (res != FR_OK) {
		fft_error("mkfs error:%d", res);
		return -1;
	}
	fft_debug("mkfs success");

	res = f_mount(&fs, "", 1);
	if (res != FR_OK) {
		fft_error("mount fatfs error:%d", res);
		return -1;
	}

    res = f_open(&fp, "test.txt", FA_CREATE_NEW|FA_WRITE);
    if (res != FR_OK) {
        fft_error("create file error:%d", res);
        return -1;
    }

    res = f_write(&fp, string, sizeof(string), &rlen);
    if (res != FR_OK) {
        fft_error("write file error:%d", res);
        f_close(&fp);
        return -1;
    }
    fft_debug("write %d", rlen);
    f_close(&fp);

    res = f_open(&fp, "test.txt", FA_READ);
    if (res != FR_OK) {
        fft_error("open file error:%d", res);
        f_close(&fp);
        return -1;
    }

    res = f_read(&fp, rxbuf, sizeof(string), &rlen);
    if (res != FR_OK) {
        fft_error("read file error:%d", res);
        f_close(&fp);
        return -1;
    }
    fft_debug("read %d", rlen);
    f_close(&fp);

    fft_hexdump(rxbuf, rlen);

    return 0;
}